package com.lifeverse.entity;

import jakarta.persistence.*;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 价值趋势实体类
 * 记录价值随时间的变化趋势
 */
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "value_trends", indexes = {
    @Index(name = "idx_value_trend_assessment", columnList = "value_assessment_id"),
    @Index(name = "idx_value_trend_timestamp", columnList = "timestamp"),
    @Index(name = "idx_value_trend_period", columnList = "period_type")
})
public class ValueTrend extends BaseEntity {
    
    /**
     * 关联的价值评估
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "value_assessment_id", nullable = false)
    private ValueAssessment valueAssessment;
    
    /**
     * 时间戳
     */
    @Column(name = "timestamp", nullable = false)
    private LocalDateTime timestamp;
    
    /**
     * 周期类型
     */
    @Column(name = "period_type", nullable = false, length = 20)
    private String periodType; // DAILY, WEEKLY, MONTHLY, QUARTERLY, YEARLY
    
    /**
     * 周期值
     */
    @Column(name = "period_value", nullable = false, precision = 15, scale = 4)
    private BigDecimal periodValue;
    
    /**
     * 累计值
     */
    @Column(name = "cumulative_value", precision = 15, scale = 4)
    private BigDecimal cumulativeValue;
    
    /**
     * 变化量
     */
    @Column(name = "change_amount", precision = 15, scale = 4)
    private BigDecimal changeAmount;
    
    /**
     * 变化率（%）
     */
    @Column(name = "change_rate", precision = 8, scale = 4)
    private BigDecimal changeRate;
    
    /**
     * 移动平均值
     */
    @Column(name = "moving_average", precision = 15, scale = 4)
    private BigDecimal movingAverage;
    
    /**
     * 趋势方向
     */
    @Column(name = "trend_direction", length = 20)
    private String trendDirection; // INCREASING, DECREASING, STABLE, VOLATILE
    
    /**
     * 趋势强度（0-100）
     */
    @Column(name = "trend_strength", precision = 5, scale = 2)
    private BigDecimal trendStrength;
    
    /**
     * 季节性因子
     */
    @Column(name = "seasonal_factor", precision = 5, scale = 4)
    private BigDecimal seasonalFactor;
    
    /**
     * 预测值
     */
    @Column(name = "predicted_value", precision = 15, scale = 4)
    private BigDecimal predictedValue;
    
    /**
     * 预测准确性（%）
     */
    @Column(name = "prediction_accuracy", precision = 5, scale = 2)
    private BigDecimal predictionAccuracy;
    
    /**
     * 异常标记
     */
    @Column(name = "is_anomaly", nullable = false)
    private Boolean isAnomaly = false;
    
    /**
     * 异常分数
     */
    @Column(name = "anomaly_score", precision = 5, scale = 2)
    private BigDecimal anomalyScore;
    
    /**
     * 影响因子（JSON格式）
     */
    @Column(name = "influence_factors", columnDefinition = "TEXT")
    private String influenceFactors;
    
    /**
     * 趋势注释
     */
    @Column(name = "trend_notes", columnDefinition = "TEXT")
    private String trendNotes;
    
    /**
     * 趋势标签（JSON格式）
     */
    @Column(name = "tags", length = 500)
    private String tags;
    
    /**
     * 趋势属性（JSON格式）
     */
    @Column(name = "attributes", columnDefinition = "TEXT")
    private String attributes;
    
    @PrePersist
    protected void onCreate() {
        super.onCreate();
        if (timestamp == null) {
            timestamp = LocalDateTime.now();
        }
    }
    
    /**
     * 计算与前一周期的变化
     */
    public void calculateChange(BigDecimal previousValue) {
        if (previousValue != null && periodValue != null) {
            this.changeAmount = periodValue.subtract(previousValue);
            
            if (previousValue.compareTo(BigDecimal.ZERO) != 0) {
                this.changeRate = changeAmount.divide(previousValue, 4, java.math.RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
            }
        }
    }
    
    /**
     * 更新趋势方向
     */
    public void updateTrendDirection() {
        if (changeRate == null) {
            this.trendDirection = "STABLE";
            return;
        }
        
        BigDecimal threshold = BigDecimal.valueOf(5); // 5%阈值
        
        if (changeRate.compareTo(threshold) > 0) {
            this.trendDirection = "INCREASING";
        } else if (changeRate.compareTo(threshold.negate()) < 0) {
            this.trendDirection = "DECREASING";
        } else {
            this.trendDirection = "STABLE";
        }
        
        // 检查波动性
        if (changeRate.abs().compareTo(BigDecimal.valueOf(20)) > 0) {
            this.trendDirection = "VOLATILE";
        }
    }
    
    /**
     * 计算趋势强度
     */
    public void calculateTrendStrength() {
        if (changeRate == null) {
            this.trendStrength = BigDecimal.ZERO;
            return;
        }
        
        // 基于变化率计算趋势强度
        BigDecimal absChangeRate = changeRate.abs();
        
        if (absChangeRate.compareTo(BigDecimal.valueOf(50)) >= 0) {
            this.trendStrength = BigDecimal.valueOf(100);
        } else {
            this.trendStrength = absChangeRate.multiply(BigDecimal.valueOf(2))
                    .min(BigDecimal.valueOf(100));
        }
    }
    
    /**
     * 检测异常
     */
    public void detectAnomaly(BigDecimal expectedValue, BigDecimal tolerance) {
        if (periodValue == null || expectedValue == null) {
            return;
        }
        
        BigDecimal difference = periodValue.subtract(expectedValue).abs();
        BigDecimal threshold = expectedValue.multiply(tolerance);
        
        this.isAnomaly = difference.compareTo(threshold) > 0;
        
        if (this.isAnomaly) {
            this.anomalyScore = difference.divide(expectedValue, 4, java.math.RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(100));
        } else {
            this.anomalyScore = BigDecimal.ZERO;
        }
    }
    
    /**
     * 计算预测准确性
     */
    public void calculatePredictionAccuracy() {
        if (predictedValue == null || periodValue == null || periodValue.compareTo(BigDecimal.ZERO) == 0) {
            this.predictionAccuracy = BigDecimal.ZERO;
            return;
        }
        
        BigDecimal error = predictedValue.subtract(periodValue).abs();
        BigDecimal errorRate = error.divide(periodValue, 4, java.math.RoundingMode.HALF_UP);
        
        this.predictionAccuracy = BigDecimal.valueOf(100).subtract(errorRate.multiply(BigDecimal.valueOf(100)))
                .max(BigDecimal.ZERO);
    }
    
    /**
     * 判断是否为上升趋势
     */
    public boolean isIncreasing() {
        return "INCREASING".equals(trendDirection);
    }
    
    /**
     * 判断是否为下降趋势
     */
    public boolean isDecreasing() {
        return "DECREASING".equals(trendDirection);
    }
    
    /**
     * 判断是否稳定
     */
    public boolean isStable() {
        return "STABLE".equals(trendDirection);
    }
    
    /**
     * 判断是否波动
     */
    public boolean isVolatile() {
        return "VOLATILE".equals(trendDirection);
    }
    
    /**
     * 判断是否为强趋势
     */
    public boolean isStrongTrend() {
        return trendStrength != null && trendStrength.compareTo(BigDecimal.valueOf(70)) >= 0;
    }
    
    /**
     * 判断是否为高异常
     */
    public boolean isHighAnomaly() {
        return isAnomaly && anomalyScore != null && anomalyScore.compareTo(BigDecimal.valueOf(50)) >= 0;
    }
}